unit Main;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, AsphyreFonts, Asphyre2D, AsphyreCanvas, AsphyreSubsc,
  AsphyreDevices, AsphyreImages, AsphyreDb, AsphyreTimers, GuiBasic,
  AsphyreTextures, AsphyreMouse, AsphyreDef, AsphyreKeyboard, AsphyreSprite,
  Math, DirectInput, Constants, Vectors2, Supply, ImpactSprite, ExtCtrls, Scripts,
  AnimParts, PathFinder, AI, NPC_Storage, Weapon_Storage, GUIEdit,
  AsphyreStates, Scenes;

type
  TGameMode = (gm_Game, gm_Menu, gm_Option, gm_AnimRed, gm_SkeletAnim, gm_Wiki,
     gm_LevelRedactor);

  TMainForm = class(TForm)
    Device: TAsphyreDevice;
    Timer: TAsphyreTimer;
    ASD: TASDb;
    Images: TAsphyreImages;
    Canvas: TAsphyreCanvas;
    Fonts: TAsphyreFonts;
    Keyboard: TAsphyreKeyboard;
    Mouses: TAsphyreMouse;
    Textures: TAsphyreTextures;
    procedure FormCreate(Sender: TObject);
    procedure DeviceInitialize(Sender: TObject; var Success: Boolean);
    procedure TimerTimer(Sender: TObject);
    procedure DeviceRender(Sender: TObject);
    procedure TimerProcess(Sender: TObject);
    procedure DeviceFinalize(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormMouseWheel(Sender: TObject; Shift: TShiftState;
      WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  MapSize:longint=2048;
  TextureSize:longint=256;

var
  MainForm: TMainForm;
  Scene:TScene;
  LastScene:TScene;
  PathSeeker:TPathSeeker;
  NPCStorage:TNPC_Storage;
  WeaponStorage:TWeapon_Storage;
  SpriteEngine:TSpriteEngine;
  Player:TPlayer;
  Wait:integer;
  Mode:TGameMode;

procedure ChangeScene(AMode:TGameMode);
procedure PushScene(NewScene:TScene);
procedure PopScene;

implementation
uses
Geometry, Wiki, Paths;

{$R *.dfm}

procedure PushScene(NewScene:TScene);
begin
  if LastScene<>nil then
  LastScene.Destroy;
  LastScene:=Scene;
  Scene:=NewScene;
end;

procedure PopScene;
var
TempScene:TScene;
begin
  TempScene:=Scene;
  Scene:=LastScene;
  LastScene:=TempScene;
end;

procedure ChangeScene(AMode:TGameMode);
var
Temp:TScene;
begin
  Mode:=AMode;
  Temp:=nil;
  with MainForm do
  case AMode of
    gm_Game:Temp:=TGameScene.Create(Device, Timer, ASD, Images, Canvas,
      Fonts, Keyboard, Mouses, Textures);
    gm_AnimRed:Temp:=TAnimationScene.Create(Device, Timer, ASD, Images, Canvas,
      Fonts, Keyboard, Mouses, Textures);
    gm_Wiki:Temp:=TWikiScene.Create(Device, Timer, ASD, Images, Canvas,
      Fonts, Keyboard, Mouses, Textures);
    gm_LevelRedactor:Temp:=TLevelRedactorScene.Create(Device, Timer, ASD, Images, Canvas,
      Fonts, Keyboard, Mouses, Textures);
  end;
  PushScene(Temp);
end;

procedure TMainForm.FormCreate(Sender: TObject);
begin
   if (not Device.Initialize()) then
   begin
        MessageDlg('Unable to initialize Asphyre device!', mtError, [mbOk], 0);
        Application.Terminate;
        Exit;
   end;
   DecimalSeparator:='.';

   ShowCursor(false);
   Mouses.Initialize;
   Keyboard.Initialize;

   ChangeScene(gm_Game);
end;

procedure TMainForm.DeviceInitialize(Sender: TObject;
  var Success: Boolean);
var
  l:integer;
begin
  Success := Images.LoadFromASDb(ASD);

  // if succeeded with images, load all fonts too
  if (Success) then
  Success := Fonts.LoadFromASDb(ASD);

  if (Success) then
  Success:= Textures.AddRenderTargets(3, 1024, 1024,true,aqHigh,alNone,false);

  if (Success) then
  Success:= Textures.AddRenderTargets(2, 1024, 1024,true,aqHigh,alNone,false);

  l:=MapSize div TextureSize;

  if (Success) then
  Success:= Textures.AddRenderTargets(sqr(l), TextureSize, TextureSize,true,aqHigh,alNone,false);

  // start rendering only if succeeded loading stuff
  Timer.Enabled := Success;
end;

procedure TMainForm.TimerTimer(Sender: TObject);
begin
  Scene.PreRender;
     // render the scene
  Device.Render(0, false);

    // do calculations while Direct3D is still rendering
  Timer.Process;

     // flip back buffers
  Device.Flip();
end;

procedure TMainForm.DeviceRender(Sender: TObject);
begin
  Scene.Render;
end;

procedure TMainForm.TimerProcess(Sender: TObject);
begin
  Keyboard.Update;
  Mouses.Update;

  inc(Wait);

  if Keyboard.Key[DIK_F1] then
  ChangeScene(gm_Game);
  if Keyboard.Key[DIK_F2] then
   ChangeScene(gm_LevelRedactor);
  if Keyboard.Key[DIK_F3] then
   ChangeScene(gm_Wiki);
  if Keyboard.Key[DIK_F4] then
   ChangeScene(gm_AnimRed);

  Scene.Move;
end;

procedure TMainForm.DeviceFinalize(Sender: TObject);
begin
  Textures.RemoveAll;
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Device.Finalize;
  Images.RemoveAll;
  ASD.Free;
end;

procedure TMainForm.FormMouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
var
i:integer;
begin
  i:=0;
  with TGameScene(Scene) do
  if Player<>nil then
  if Mode=gm_Game then
  begin
    repeat
      if Mouse.WheelPresent then
      Player.ActivePower:=Player.ActivePower+WheelDelta div abs(WheelDelta);
      while not InRange(Player.ActivePower,0,9) do
      begin
        if Player.ActivePower>9 then
        Player.ActivePower:=Player.ActivePower-10;
        if Player.ActivePower<0 then
        Player.ActivePower:=10+Player.ActivePower;
      end;
      i:=i+1;
    until (Player.Powers[Player.ActivePower]>0)or(i>10);
  end;

  if Mode=gm_Wiki then
  with TWikiScene(Scene) do
  begin
    if PtInRect2(Bounds2(Wiki.ListX,Wiki.ListY,Wiki.ListWidth,
      Wiki.ListHeight),Point2(mouse.CursorPos.X,mouse.CursorPos.y)) then
    Wiki.ListScrollY:=Wiki.ListScrollY-WheelDelta/2;
    if PtInRect2(Bounds2(Wiki.PageX,Wiki.PageY,Wiki.PageWidth,
      Wiki.PageHeight),Point2(mouse.CursorPos.X,mouse.CursorPos.y)) then
    Wiki.PageScrollY:=Wiki.PageScrollY-WheelDelta/2;
  end;
end;

end.



